home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Online / x3270 / unix_files / ansi.c < prev    next >
Encoding:
C/C++ Source or Header  |  2009-01-25  |  34.8 KB  |  1,512 lines

  1. /*
  2.  * Copyright 1993, 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
  3.  *  Permission to use, copy, modify, and distribute this software and its
  4.  *  documentation for any purpose and without fee is hereby granted,
  5.  *  provided that the above copyright notice appear in all copies and that
  6.  *  both that copyright notice and this permission notice appear in
  7.  *  supporting documentation.
  8.  */
  9.  
  10. /*
  11.  *    ansi.c
  12.  *        ANSI terminal emulation.
  13.  */
  14.  
  15. #include "globals.h"
  16.  
  17. #if defined(X3270_ANSI) /*[*/
  18.  
  19. #if defined(X3270_DISPLAY) /*[*/
  20. #include <X11/Shell.h>
  21. #endif /*]*/
  22.  
  23. #include "appres.h"
  24. #include "ctlr.h"
  25.  
  26. #include "ansic.h"
  27. #include "ctlrc.h"
  28. #include "hostc.h"
  29. #include "screenc.h"
  30. #include "scrollc.h"
  31. #include "tablesc.h"
  32. #include "telnetc.h"
  33. #include "trace_dsc.h"
  34.  
  35. #define    SC    1    /* save cursor position */
  36. #define RC    2    /* restore cursor position */
  37. #define NL    3    /* new line */
  38. #define UP    4    /* cursor up */
  39. #define    E2    5    /* second level of ESC processing */
  40. #define rS    6    /* reset */
  41. #define IC    7    /* insert chars */
  42. #define DN    8    /* cursor down */
  43. #define RT    9    /* cursor right */
  44. #define LT    10    /* cursor left */
  45. #define CM    11    /* cursor motion */
  46. #define ED    12    /* erase in display */
  47. #define EL    13    /* erase in line */
  48. #define IL    14    /* insert lines */
  49. #define DL    15    /* delete lines */
  50. #define DC    16    /* delete characters */
  51. #define    SG    17    /* set graphic rendition */
  52. #define BL    18    /* ring bell */
  53. #define NP    19    /* new page */
  54. #define BS    20    /* backspace */
  55. #define CR    21    /* carriage return */
  56. #define LF    22    /* line feed */
  57. #define HT    23    /* horizontal tab */
  58. #define E1    24    /* first level of ESC processing */
  59. #define Xx    25    /* undefined control character (nop) */
  60. #define Pc    26    /* printing character */
  61. #define Sc    27    /* semicolon (after ESC [) */
  62. #define Dg    28    /* digit (after ESC [ or ESC [ ?) */
  63. #define RI    29    /* reverse index */
  64. #define DA    30    /* send device attributes */
  65. #define SM    31    /* set mode */
  66. #define RM    32    /* reset mode */
  67. #define DO    33    /* return terminal ID (obsolete) */
  68. #define SR    34    /* device status report */
  69. #define CS    35    /* character set designate */
  70. #define E3    36    /* third level of ESC processing */
  71. #define DS    37    /* DEC private set */
  72. #define DR    38    /* DEC private reset */
  73. #define DV    39    /* DEC private save */
  74. #define DT    40    /* DEC private restore */
  75. #define SS    41    /* set scrolling region */
  76. #define TM    42    /* text mode (ESC ]) */
  77. #define T2    43    /* semicolon (after ESC ]) */
  78. #define TX    44    /* text parameter (after ESC ] n ;) */
  79. #define TB    45    /* text parameter done (ESC ] n ; xxx BEL) */
  80. #define TS    46    /* tab set */
  81. #define TC    47    /* tab clear */
  82. #define C2    48    /* character set designate (finish) */
  83. #define G0    49    /* select G0 character set */
  84. #define G1    50    /* select G1 character set */
  85. #define G2    51    /* select G2 character set */
  86. #define G3    52    /* select G3 character set */
  87. #define S2    53    /* select G2 for next character */
  88. #define S3    54    /* select G3 for next character */
  89.  
  90. static enum state {
  91.     DATA = 0, ESC = 1, CSDES = 2,
  92.     N1 = 3, DECP = 4, TEXT = 5, TEXT2 = 6
  93. } state = DATA;
  94.  
  95. static enum state ansi_data_mode(int, int);
  96. static enum state dec_save_cursor(int, int);
  97. static enum state dec_restore_cursor(int, int);
  98. static enum state ansi_newline(int, int);
  99. static enum state ansi_cursor_up(int, int);
  100. static enum state ansi_esc2(int, int);
  101. static enum state ansi_reset(int, int);
  102. static enum state ansi_insert_chars(int, int);
  103. static enum state ansi_cursor_down(int, int);
  104. static enum state ansi_cursor_right(int, int);
  105. static enum state ansi_cursor_left(int, int);
  106. static enum state ansi_cursor_motion(int, int);
  107. static enum state ansi_erase_in_display(int, int);
  108. static enum state ansi_erase_in_line(int, int);
  109. static enum state ansi_insert_lines(int, int);
  110. static enum state ansi_delete_lines(int, int);
  111. static enum state ansi_delete_chars(int, int);
  112. static enum state ansi_sgr(int, int);
  113. static enum state ansi_bell(int, int);
  114. static enum state ansi_newpage(int, int);
  115. static enum state ansi_backspace(int, int);
  116. static enum state ansi_cr(int, int);
  117. static enum state ansi_lf(int, int);
  118. static enum state ansi_htab(int, int);
  119. static enum state ansi_escape(int, int);
  120. static enum state ansi_nop(int, int);
  121. static enum state ansi_printing(int, int);
  122. static enum state ansi_semicolon(int, int);
  123. static enum state ansi_digit(int, int);
  124. static enum state ansi_reverse_index(int, int);
  125. static enum state ansi_send_attributes(int, int);
  126. static enum state ansi_set_mode(int, int);
  127. static enum state ansi_reset_mode(int, int);
  128. static enum state dec_return_terminal_id(int, int);
  129. static enum state ansi_status_report(int, int);
  130. static enum state ansi_cs_designate(int, int);
  131. static enum state ansi_esc3(int, int);
  132. static enum state dec_set(int, int);
  133. static enum state dec_reset(int, int);
  134. static enum state dec_save(int, int);
  135. static enum state dec_restore(int, int);
  136. static enum state dec_scrolling_region(int, int);
  137. static enum state xterm_text_mode(int, int);
  138. static enum state xterm_text_semicolon(int, int);
  139. static enum state xterm_text(int, int);
  140. static enum state xterm_text_do(int, int);
  141. static enum state ansi_htab_set(int, int);
  142. static enum state ansi_htab_clear(int, int);
  143. static enum state ansi_cs_designate2(int, int);
  144. static enum state ansi_select_g0(int, int);
  145. static enum state ansi_select_g1(int, int);
  146. static enum state ansi_select_g2(int, int);
  147. static enum state ansi_select_g3(int, int);
  148. static enum state ansi_one_g2(int, int);
  149. static enum state ansi_one_g3(int, int);
  150.  
  151. static enum state (*ansi_fn[])(int, int) = {
  152. /* 0 */        ansi_data_mode,
  153. /* 1 */        dec_save_cursor,
  154. /* 2 */        dec_restore_cursor,
  155. /* 3 */        ansi_newline,
  156. /* 4 */        ansi_cursor_up,
  157. /* 5 */        ansi_esc2,
  158. /* 6 */        ansi_reset,
  159. /* 7 */        ansi_insert_chars,
  160. /* 8 */        ansi_cursor_down,
  161. /* 9 */        ansi_cursor_right,
  162. /* 10 */    ansi_cursor_left,
  163. /* 11 */    ansi_cursor_motion,
  164. /* 12 */    ansi_erase_in_display,
  165. /* 13 */    ansi_erase_in_line,
  166. /* 14 */    ansi_insert_lines,
  167. /* 15 */    ansi_delete_lines,
  168. /* 16 */    ansi_delete_chars,
  169. /* 17 */    ansi_sgr,
  170. /* 18 */    ansi_bell,
  171. /* 19 */    ansi_newpage,
  172. /* 20 */    ansi_backspace,
  173. /* 21 */    ansi_cr,
  174. /* 22 */    ansi_lf,
  175. /* 23 */    ansi_htab,
  176. /* 24 */    ansi_escape,
  177. /* 25 */    ansi_nop,
  178. /* 26 */    ansi_printing,
  179. /* 27 */    ansi_semicolon,
  180. /* 28 */    ansi_digit,
  181. /* 29 */    ansi_reverse_index,
  182. /* 30 */    ansi_send_attributes,
  183. /* 31 */    ansi_set_mode,
  184. /* 32 */    ansi_reset_mode,
  185. /* 33 */    dec_return_terminal_id,
  186. /* 34 */    ansi_status_report,
  187. /* 35 */    ansi_cs_designate,
  188. /* 36 */    ansi_esc3,
  189. /* 37 */    dec_set,
  190. /* 38 */    dec_reset,
  191. /* 39 */    dec_save,
  192. /* 40 */    dec_restore,
  193. /* 41 */    dec_scrolling_region,
  194. /* 42 */    xterm_text_mode,
  195. /* 43 */    xterm_text_semicolon,
  196. /* 44 */    xterm_text,
  197. /* 45 */    xterm_text_do,
  198. /* 46 */    ansi_htab_set,
  199. /* 47 */    ansi_htab_clear,
  200. /* 48 */    ansi_cs_designate2,
  201. /* 49 */    ansi_select_g0,
  202. /* 50 */    ansi_select_g1,
  203. /* 51 */    ansi_select_g2,
  204. /* 52 */    ansi_select_g3,
  205. /* 53 */    ansi_one_g2,
  206. /* 54 */    ansi_one_g3,
  207. };
  208.  
  209. static unsigned char st[7][256] = {
  210. /*
  211.  * State table for base processing (state == DATA)
  212.  */
  213. {
  214.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  215. /* 00 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,BL,BS,HT,LF,LF,NP,CR,G1,G0,
  216. /* 10 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,E1,Xx,Xx,Xx,Xx,
  217. /* 20 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  218. /* 30 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  219. /* 40 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  220. /* 50 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  221. /* 60 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  222. /* 70 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Xx,
  223. /* 80 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,
  224. /* 90 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,
  225. /* a0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  226. /* b0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  227. /* c0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  228. /* d0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  229. /* e0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  230. /* f0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc
  231. },
  232.  
  233. /*
  234.  * State table for ESC processing (state == ESC)
  235.  */
  236. {
  237.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  238. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  239. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  240. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0,CS,CS,CS,CS, 0, 0, 0, 0,
  241. /* 30 */    0, 0, 0, 0, 0, 0, 0,SC,RC, 0, 0, 0, 0, 0, 0, 0,
  242. /* 40 */    0, 0, 0, 0, 0,NL, 0, 0,TS, 0, 0, 0, 0,RI,S2,S3,
  243. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,E2, 0,TM, 0, 0,
  244. /* 60 */    0, 0, 0,rS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,G2,G3,
  245. /* 70 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  246. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  247. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  248. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  249. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  250. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  251. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  252. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  253. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  254. },
  255.  
  256. /*
  257.  * State table for ESC ()*+ C processing (state == CSDES)
  258.  */
  259. {
  260.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  261. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  262. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  263. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  264. /* 30 */       C2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  265. /* 40 */    0,C2,C2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  266. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  267. /* 60 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  268. /* 70 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  269. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  270. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  271. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  272. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  273. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  274. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  275. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  276. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  277. },
  278.  
  279. /*
  280.  * State table for ESC [ processing (state == N1)
  281.  */
  282. {
  283.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  284. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  285. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  286. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  287. /* 30 */       Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg, 0,Sc, 0, 0, 0,E3,
  288. /* 40 */       IC,UP,DN,RT,LT, 0, 0, 0,CM, 0,ED,EL,IL,DL, 0, 0,
  289. /* 50 */       DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  290. /* 60 */    0, 0, 0,DA, 0, 0,CM,TC,SM, 0, 0, 0,RM,SG,SR, 0,
  291. /* 70 */    0, 0,SS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  292. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  293. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  294. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  295. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  296. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  297. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  298. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  299. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  300. },
  301.  
  302. /*
  303.  * State table for ESC [ ? processing (state == DECP)
  304.  */
  305. {
  306.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  307. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  308. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  309. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  310. /* 30 */       Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg, 0, 0, 0, 0, 0, 0,
  311. /* 40 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  312. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  313. /* 60 */    0, 0, 0, 0, 0, 0, 0, 0,DS, 0, 0, 0,DR, 0, 0, 0,
  314. /* 70 */    0, 0,DT,DV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  315. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  316. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  317. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  318. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  319. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  320. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  321. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  322. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  323. },
  324.  
  325. /*
  326.  * State table for ESC ] processing (state == TEXT)
  327.  */
  328. {
  329.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  330. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  331. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  332. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  333. /* 30 */       Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg, 0,T2, 0, 0, 0, 0,
  334. /* 40 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  335. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  336. /* 60 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  337. /* 70 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  338. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  339. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  340. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  341. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  342. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  343. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  344. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  345. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  346. },
  347.  
  348. /*
  349.  * State table for ESC ] n ; processing (state == TEXT2)
  350.  */
  351. {
  352.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  353. /* 00 */        0, 0, 0, 0, 0, 0, 0,TB, 0, 0, 0, 0, 0, 0, 0, 0,
  354. /* 10 */        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  355. /* 20 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  356. /* 30 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  357. /* 40 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  358. /* 50 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  359. /* 60 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  360. /* 70 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,Xx,
  361. /* 80 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  362. /* 90 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  363. /* a0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  364. /* b0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  365. /* c0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  366. /* d0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  367. /* e0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  368. /* f0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX
  369. },
  370. };
  371.  
  372. /* Character sets. */
  373. #define CS_G0        0
  374. #define CS_G1        1
  375. #define CS_G2        2
  376. #define CS_G3        3
  377.  
  378. /* Character set designations. */
  379. #define CSD_LD        0
  380. #define CSD_UK        1
  381. #define CSD_US        2
  382.  
  383. static int      saved_cursor = 0;
  384. #define NN    20
  385. static int      n[NN], nx = 0;
  386. #define NT    256
  387. static char     text[NT + 1];
  388. static int      tx = 0;
  389. static int      ansi_ch;
  390. static unsigned char gr = 0;
  391. static unsigned char saved_gr = 0;
  392. static unsigned char fg = 0;
  393. static unsigned char saved_fg = 0;
  394. static unsigned char bg = 0;
  395. static unsigned char saved_bg = 0;
  396. static int    cset = CS_G0;
  397. static int    saved_cset = CS_G0;
  398. static int    csd[4] = { CSD_US, CSD_US, CSD_US, CSD_US };
  399. static int    saved_csd[4] = { CSD_US, CSD_US, CSD_US, CSD_US };
  400. static int    once_cset = -1;
  401. static int      insert_mode = 0;
  402. static int      auto_newline_mode = 0;
  403. static int      appl_cursor = 0;
  404. static int      saved_appl_cursor = 0;
  405. static int      wraparound_mode = 1;
  406. static int      saved_wraparound_mode = 1;
  407. static int      rev_wraparound_mode = 0;
  408. static int      saved_rev_wraparound_mode = 0;
  409. static Boolean  saved_altbuffer = False;
  410. static int      scroll_top = -1;
  411. static int      scroll_bottom = -1;
  412. static unsigned char *tabs = (unsigned char *) NULL;
  413. static char    gnnames[] = "()*+";
  414. static char    csnames[] = "0AB";
  415. static int    cs_to_change;
  416.  
  417. static Boolean  held_wrap = False;
  418.  
  419. static void    ansi_scroll(void);
  420.  
  421. static enum state
  422. ansi_data_mode(int ig1 unused, int ig2 unused)
  423. {
  424.     return DATA;
  425. }
  426.  
  427. static enum state
  428. dec_save_cursor(int ig1 unused, int ig2 unused)
  429. {
  430.     int i;
  431.  
  432.     saved_cursor = cursor_addr;
  433.     saved_cset = cset;
  434.     for (i = 0; i < 4; i++)
  435.         saved_csd[i] = csd[i];
  436.     saved_fg = fg;
  437.     saved_bg = bg;
  438.     saved_gr = gr;
  439.     return DATA;
  440. }
  441.  
  442. static enum state
  443. dec_restore_cursor(int ig1 unused, int ig2 unused)
  444. {
  445.     int i;
  446.  
  447.     cset = saved_cset;
  448.     for (i = 0; i < 4; i++)
  449.         csd[i] = saved_csd[i];
  450.     fg = saved_fg;
  451.     bg = saved_bg;
  452.     gr = saved_gr;
  453.     cursor_move(saved_cursor);
  454.     held_wrap = False;
  455.     return DATA;
  456. }
  457.  
  458. static enum state
  459. ansi_newline(int ig1 unused, int ig2 unused)
  460. {
  461.     int nc;
  462.  
  463.     cursor_move(cursor_addr - (cursor_addr % COLS));
  464.     nc = cursor_addr + COLS;
  465.     if (nc < scroll_bottom * COLS)
  466.         cursor_move(nc);
  467.     else
  468.         ansi_scroll();
  469.     held_wrap = False;
  470.     return DATA;
  471. }
  472.  
  473. static enum state
  474. ansi_cursor_up(int nn, int ig2 unused)
  475. {
  476.     int rr;
  477.  
  478.     if (nn < 1)
  479.         nn = 1;
  480.     rr = cursor_addr / COLS;
  481.     if (rr - nn < 0)
  482.         cursor_move(cursor_addr % COLS);
  483.     else
  484.         cursor_move(cursor_addr - (nn * COLS));
  485.     held_wrap = False;
  486.     return DATA;
  487. }
  488.  
  489. static enum state
  490. ansi_esc2(int ig1 unused, int ig2 unused)
  491. {
  492.     register int    i;
  493.  
  494.     for (i = 0; i < NN; i++)
  495.         n[i] = 0;
  496.     nx = 0;
  497.     return N1;
  498. }
  499.  
  500. static enum state
  501. ansi_reset(int ig1 unused, int ig2 unused)
  502. {
  503.     int i;
  504.     static Boolean first = True;
  505.  
  506.     gr = 0;
  507.     saved_gr = 0;
  508.     fg = 0;
  509.     saved_fg = 0;
  510.     bg = 0;
  511.     saved_bg = 0;
  512.     cset = CS_G0;
  513.     saved_cset = CS_G0;
  514.     csd[0] = csd[1] = csd[2] = csd[3] = CSD_US;
  515.     saved_csd[0] = saved_csd[1] = saved_csd[2] = saved_csd[3] = CSD_US;
  516.     once_cset = -1;
  517.     saved_cursor = 0;
  518.     insert_mode = 0;
  519.     auto_newline_mode = 0;
  520.     appl_cursor = 0;
  521.     saved_appl_cursor = 0;
  522.     wraparound_mode = 1;
  523.     saved_wraparound_mode = 1;
  524.     rev_wraparound_mode = 0;
  525.     saved_rev_wraparound_mode = 0;
  526.     saved_altbuffer = False;
  527.     scroll_top = 1;
  528.     scroll_bottom = ROWS;
  529.     if (tabs == (unsigned char *)NULL)
  530.         Free((char *)tabs);
  531.     tabs = (unsigned char *)Malloc((COLS+7)/8);
  532.     for (i = 0; i < (COLS+7)/8; i++)
  533.         tabs[i] = 0x01;
  534.     held_wrap = False;
  535.     if (!first) {
  536.         ctlr_altbuffer(True);
  537.         ctlr_aclear(0, ROWS * COLS, 1);
  538.         ctlr_altbuffer(False);
  539.         ctlr_clear(False);
  540.     }
  541.     first = False;
  542.     return DATA;
  543. }
  544.  
  545. static enum state
  546. ansi_insert_chars(int nn, int ig2 unused)
  547. {
  548.     int cc = cursor_addr % COLS;    /* current col */
  549.     int mc = COLS - cc;        /* max chars that can be inserted */
  550.     int ns;                /* chars that are shifting */
  551.  
  552.     if (nn < 1)
  553.         nn = 1;
  554.     if (nn > mc)
  555.         nn = mc;
  556.  
  557.     /* Move the surviving chars right */
  558.     ns = mc - nn;
  559.     if (ns)
  560.         ctlr_bcopy(cursor_addr, cursor_addr + nn, ns, 1);
  561.  
  562.     /* Clear the middle of the line */
  563.     ctlr_aclear(cursor_addr, nn, 1);
  564.     return DATA;
  565. }
  566.  
  567. static enum state
  568. ansi_cursor_down(int nn, int ig2 unused)
  569. {
  570.     int rr;
  571.  
  572.     if (nn < 1)
  573.         nn = 1;
  574.     rr = cursor_addr / COLS;
  575.     if (rr + nn >= ROWS)
  576.         cursor_move((ROWS-1)*COLS + (cursor_addr%COLS));
  577.     else
  578.         cursor_move(cursor_addr + (nn * COLS));
  579.     held_wrap = False;
  580.     return DATA;
  581. }
  582.  
  583. static enum state
  584. ansi_cursor_right(int nn, int ig2 unused)
  585. {
  586.     int cc;
  587.  
  588.     if (nn < 1)
  589.         nn = 1;
  590.     cc = cursor_addr % COLS;
  591.     if (cc == COLS-1)
  592.         return DATA;
  593.     if (cc + nn >= COLS)
  594.         nn = COLS - 1 - cc;
  595.     cursor_move(cursor_addr + nn);
  596.     held_wrap = False;
  597.     return DATA;
  598. }
  599.  
  600. static enum state
  601. ansi_cursor_left(int nn, int ig2 unused)
  602. {
  603.     int cc;
  604.  
  605.     if (held_wrap) {
  606.         held_wrap = False;
  607.         return DATA;
  608.     }
  609.     if (nn < 1)
  610.         nn = 1;
  611.     cc = cursor_addr % COLS;
  612.     if (!cc)
  613.         return DATA;
  614.     if (nn > cc)
  615.         nn = cc;
  616.     cursor_move(cursor_addr - nn);
  617.     return DATA;
  618. }
  619.  
  620. static enum state
  621. ansi_cursor_motion(int n1, int n2)
  622. {
  623.     if (n1 < 1) n1 = 1;
  624.     if (n1 > ROWS) n1 = ROWS;
  625.     if (n2 < 1) n2 = 1;
  626.     if (n2 > COLS) n2 = COLS;
  627.     cursor_move((n1 - 1) * COLS + (n2 - 1));
  628.     held_wrap = False;
  629.     return DATA;
  630. }
  631.  
  632. static enum state
  633. ansi_erase_in_display(int nn, int ig2 unused)
  634. {
  635.     switch (nn) {
  636.         case 0:    /* below */
  637.         ctlr_aclear(cursor_addr, (ROWS * COLS) - cursor_addr, 1);
  638.         break;
  639.         case 1:    /* above */
  640.         ctlr_aclear(0, cursor_addr + 1, 1);
  641.         break;
  642.         case 2:    /* all (without moving cursor) */
  643.         if (cursor_addr == 0 && !is_altbuffer)
  644.             scroll_save(ROWS, True);
  645.         ctlr_aclear(0, ROWS * COLS, 1);
  646.         break;
  647.     }
  648.     return DATA;
  649. }
  650.  
  651. static enum state
  652. ansi_erase_in_line(int nn, int ig2 unused)
  653. {
  654.     int nc = cursor_addr % COLS;
  655.  
  656.     switch (nn) {
  657.         case 0:    /* to right */
  658.         ctlr_aclear(cursor_addr, COLS - nc, 1);
  659.         break;
  660.         case 1:    /* to left */
  661.         ctlr_aclear(cursor_addr - nc, nc+1, 1);
  662.         break;
  663.         case 2:    /* all */
  664.         ctlr_aclear(cursor_addr - nc, COLS, 1);
  665.         break;
  666.     }
  667.     return DATA;
  668. }
  669.  
  670. static enum state
  671. ansi_insert_lines(int nn, int ig2 unused)
  672. {
  673.     int rr = cursor_addr / COLS;    /* current row */
  674.     int mr = scroll_bottom - rr;    /* rows left at and below this one */
  675.     int ns;                /* rows that are shifting */
  676.  
  677.     /* If outside of the scrolling region, do nothing */
  678.     if (rr < scroll_top - 1 || rr >= scroll_bottom)
  679.         return DATA;
  680.  
  681.     if (nn < 1)
  682.         nn = 1;
  683.     if (nn > mr)
  684.         nn = mr;
  685.     
  686.     /* Move the victims down */
  687.     ns = mr - nn;
  688.     if (ns)
  689.         ctlr_bcopy(rr * COLS, (rr + nn) * COLS, ns * COLS, 1);
  690.  
  691.     /* Clear the middle of the screen */
  692.     ctlr_aclear(rr * COLS, nn * COLS, 1);
  693.     return DATA;
  694. }
  695.  
  696. static enum state
  697. ansi_delete_lines(int nn, int ig2 unused)
  698. {
  699.     int rr = cursor_addr / COLS;    /* current row */
  700.     int mr = scroll_bottom - rr;    /* max rows that can be deleted */
  701.     int ns;                /* rows that are shifting */
  702.  
  703.     /* If outside of the scrolling region, do nothing */
  704.     if (rr < scroll_top - 1 || rr >= scroll_bottom)
  705.         return DATA;
  706.  
  707.     if (nn < 1)
  708.         nn = 1;
  709.     if (nn > mr)
  710.         nn = mr;
  711.  
  712.     /* Move the surviving rows up */
  713.     ns = mr - nn;
  714.     if (ns)
  715.         ctlr_bcopy((rr + nn) * COLS, rr * COLS, ns * COLS, 1);
  716.  
  717.     /* Clear the rest of the screen */
  718.     ctlr_aclear((rr + ns) * COLS, nn * COLS, 1);
  719.     return DATA;
  720. }
  721.  
  722. static enum state
  723. ansi_delete_chars(int nn, int ig2 unused)
  724. {
  725.     int cc = cursor_addr % COLS;    /* current col */
  726.     int mc = COLS - cc;        /* max chars that can be deleted */
  727.     int ns;                /* chars that are shifting */
  728.  
  729.     if (nn < 1)
  730.         nn = 1;
  731.     if (nn > mc)
  732.         nn = mc;
  733.  
  734.     /* Move the surviving chars left */
  735.     ns = mc - nn;
  736.     if (ns)
  737.         ctlr_bcopy(cursor_addr + nn, cursor_addr, ns, 1);
  738.  
  739.     /* Clear the end of the line */
  740.     ctlr_aclear(cursor_addr + ns, nn, 1);
  741.     return DATA;
  742. }
  743.  
  744. static enum state
  745. ansi_sgr(int ig1 unused, int ig2 unused)
  746. {
  747.     int i;
  748.  
  749.     for (i = 0; i <= nx && i < NN; i++)
  750.         switch (n[i]) {
  751.         case 0:
  752.             gr = 0;
  753.             fg = 0;
  754.             bg = 0;
  755.             break;
  756.         case 1:
  757.             gr |= GR_INTENSIFY;
  758.             break;
  759.         case 4:
  760.             gr |= GR_UNDERLINE;
  761.             break;
  762.         case 5:
  763.             gr |= GR_BLINK;
  764.             break;
  765.         case 7:
  766.             gr |= GR_REVERSE;
  767.             break;
  768.         case 30:
  769.             fg = 0xf0;    /* black */
  770.             break;
  771.         case 31:
  772.             fg = 0xf2;    /* red */
  773.             break;
  774.         case 32:
  775.             fg = 0xf4;    /* green */
  776.             break;
  777.         case 33:
  778.             fg = 0xf6;    /* yellow */
  779.             break;
  780.         case 34:
  781.             fg = 0xf1;    /* blue */
  782.             break;
  783.         case 35:
  784.             fg = 0xf3;    /* megenta */
  785.             break;
  786.         case 36:
  787.             fg = 0xfd;    /* cyan */
  788.             break;
  789.         case 37:
  790.             fg = 0xff;    /* white */
  791.             break;
  792.         case 39:
  793.             fg = 0;    /* default */
  794.             break;
  795.         case 40:
  796.             bg = 0xf0;    /* black */
  797.             break;
  798.         case 41:
  799.             bg = 0xf2;    /* red */
  800.             break;
  801.         case 42:
  802.             bg = 0xf4;    /* green */
  803.             break;
  804.         case 43:
  805.             bg = 0xf6;    /* yellow */
  806.             break;
  807.         case 44:
  808.             bg = 0xf1;    /* blue */
  809.             break;
  810.         case 45:
  811.             bg = 0xf3;    /* megenta */
  812.             break;
  813.         case 46:
  814.             bg = 0xfd;    /* cyan */
  815.             break;
  816.         case 47:
  817.             bg = 0xff;    /* white */
  818.             break;
  819.         case 49:
  820.             bg = 0;    /* default */
  821.             break;
  822.         }
  823.  
  824.     return DATA;
  825. }
  826.  
  827. static enum state
  828. ansi_bell(int ig1 unused, int ig2 unused)
  829. {
  830.     ring_bell();
  831.     return DATA;
  832. }
  833.  
  834. static enum state
  835. ansi_newpage(int ig1 unused, int ig2 unused)
  836. {
  837.     ctlr_clear(False);
  838.     return DATA;
  839. }
  840.  
  841. static enum state
  842. ansi_backspace(int ig1 unused, int ig2 unused)
  843. {
  844.     if (held_wrap) {
  845.         held_wrap = False;
  846.         return DATA;
  847.     }
  848.     if (rev_wraparound_mode) {
  849.         if (cursor_addr > (scroll_top - 1) * COLS)
  850.             cursor_move(cursor_addr - 1);
  851.     } else {
  852.         if (cursor_addr % COLS)
  853.             cursor_move(cursor_addr - 1);
  854.     }
  855.     return DATA;
  856. }
  857.  
  858. static enum state
  859. ansi_cr(int ig1 unused, int ig2 unused)
  860. {
  861.     if (cursor_addr % COLS)
  862.         cursor_move(cursor_addr - (cursor_addr % COLS));
  863.     if (auto_newline_mode)
  864.         (void) ansi_lf(0, 0);
  865.     held_wrap = False;
  866.     return DATA;
  867. }
  868.  
  869. static enum state
  870. ansi_lf(int ig1 unused, int ig2 unused)
  871. {
  872.     int nc = cursor_addr + COLS;
  873.  
  874.     held_wrap = False;
  875.  
  876.     /* If we're below the scrolling region, don't scroll. */
  877.     if ((cursor_addr / COLS) >= scroll_bottom) {
  878.         if (nc < ROWS * COLS)
  879.             cursor_move(nc);
  880.         return DATA;
  881.     }
  882.  
  883.     if (nc < scroll_bottom * COLS)
  884.         cursor_move(nc);
  885.     else
  886.         ansi_scroll();
  887.     return DATA;
  888. }
  889.  
  890. static enum state
  891. ansi_htab(int ig1 unused, int ig2 unused)
  892. {
  893.     int col = cursor_addr % COLS;
  894.     int i;
  895.  
  896.     held_wrap = False;
  897.     if (col == COLS-1)
  898.         return DATA;
  899.     for (i = col+1; i < COLS-1; i++)
  900.         if (tabs[i/8] & 1<<(i%8))
  901.             break;
  902.     cursor_move(cursor_addr - col + i);
  903.     return DATA;
  904. }
  905.  
  906. static enum state
  907. ansi_escape(int ig1 unused, int ig2 unused)
  908. {
  909.     return ESC;
  910. }
  911.  
  912. static enum state
  913. ansi_nop(int ig1 unused, int ig2 unused)
  914. {
  915.     return DATA;
  916. }
  917.  
  918. #define PWRAP { \
  919.     nc = cursor_addr + 1; \
  920.     if (nc < scroll_bottom * COLS) \
  921.         cursor_move(nc); \
  922.     else { \
  923.         if (cursor_addr / COLS >= scroll_bottom) \
  924.             cursor_move(cursor_addr / COLS * COLS); \
  925.         else { \
  926.             ansi_scroll(); \
  927.             cursor_move(nc - COLS); \
  928.         } \
  929.     } \
  930. }
  931.  
  932. static enum state
  933. ansi_printing(int ig1 unused, int ig2 unused)
  934. {
  935.     int nc;
  936.  
  937.     if (held_wrap) {
  938.         PWRAP;
  939.         held_wrap = False;
  940.     }
  941.  
  942.     if (insert_mode)
  943.         (void) ansi_insert_chars(1, 0);
  944.     switch (csd[(once_cset != -1) ? once_cset : cset]) {
  945.         case CSD_LD:    /* line drawing "0" */
  946.         if (ansi_ch >= 0x5f && ansi_ch <= 0x7e)
  947.             ctlr_add(cursor_addr, (unsigned char)(ansi_ch - 0x5f),
  948.                 2);
  949.         else
  950.             ctlr_add(cursor_addr, asc2cg[ansi_ch], 0);
  951.         break;
  952.         case CSD_UK:    /* UK "A" */
  953.         if (ansi_ch == '#')
  954.             ctlr_add(cursor_addr, 0x1e, 2);
  955.         else
  956.             ctlr_add(cursor_addr, asc2cg[ansi_ch], 0);
  957.         break;
  958.         case CSD_US:    /* US "B" */
  959.         ctlr_add(cursor_addr, asc2cg[ansi_ch], 0);
  960.         break;
  961.     }
  962.     once_cset = -1;
  963.     ctlr_add_gr(cursor_addr, gr);
  964.     ctlr_add_fg(cursor_addr, fg);
  965.     ctlr_add_bg(cursor_addr, bg);
  966.     if (wraparound_mode) {
  967.         /*
  968.          * There is a fascinating behavior of xterm which we will
  969.          * attempt to emulate here.  When a character is printed in the
  970.          * last column, the cursor sticks there, rather than wrapping
  971.          * to the next line.  Another printing character will put the
  972.          * cursor in column 2 of the next line.  One cursor-left
  973.          * sequence won't budge it; two will.  Saving and restoring
  974.          * the cursor won't move the cursor, but will cancel all of
  975.          * the above behaviors...
  976.          *
  977.          * In my opinion, very strange, but among other things, 'vi'
  978.          * depends on it!
  979.          */
  980.         if (!((cursor_addr + 1) % COLS)) {
  981.             held_wrap = True;
  982.         } else {
  983.             PWRAP;
  984.         }
  985.     } else {
  986.         if ((cursor_addr % COLS) != (COLS - 1))
  987.             cursor_move(cursor_addr + 1);
  988.     }
  989.     return DATA;
  990. }
  991.  
  992. static enum state
  993. ansi_semicolon(int ig1 unused, int ig2 unused)
  994. {
  995.     if (nx >= NN)
  996.         return DATA;
  997.     nx++;
  998.     return state;
  999. }
  1000.  
  1001. static enum state
  1002. ansi_digit(int ig1 unused, int ig2 unused)
  1003. {
  1004.     n[nx] = (n[nx] * 10) + (ansi_ch - '0');
  1005.     return state;
  1006. }
  1007.  
  1008. static enum state
  1009. ansi_reverse_index(int ig1 unused, int ig2 unused)
  1010. {
  1011.     int rr = cursor_addr / COLS;    /* current row */
  1012.     int np = (scroll_top - 1) - rr;    /* number of rows in the scrolling
  1013.                        region, above this line */
  1014.     int ns;                /* number of rows to scroll */
  1015.     int nn = 1;            /* number of rows to index */
  1016.  
  1017.     held_wrap = False;
  1018.  
  1019.     /* If the cursor is above the scrolling region, do a simple margined
  1020.        cursor up.  */
  1021.     if (np < 0) {
  1022.         (void) ansi_cursor_up(nn, 0);
  1023.         return DATA;
  1024.     }
  1025.  
  1026.     /* Split the number of lines to scroll into ns */
  1027.     if (nn > np) {
  1028.         ns = nn - np;
  1029.         nn = np;
  1030.     } else
  1031.         ns = 0;
  1032.  
  1033.     /* Move the cursor up without scrolling */
  1034.     if (nn)
  1035.         (void) ansi_cursor_up(nn, 0);
  1036.  
  1037.     /* Insert lines at the top for backward scroll */
  1038.     if (ns)
  1039.         (void) ansi_insert_lines(ns, 0);
  1040.  
  1041.     return DATA;
  1042. }
  1043.  
  1044. static enum state
  1045. ansi_send_attributes(int nn, int ig2 unused)
  1046. {
  1047.     if (!nn)
  1048.         net_sends("\033[?1;2c");
  1049.     return DATA;
  1050. }
  1051.  
  1052. static enum state
  1053. dec_return_terminal_id(int ig1 unused, int ig2 unused)
  1054. {
  1055.     return ansi_send_attributes(0, 0);
  1056. }
  1057.  
  1058. static enum state
  1059. ansi_set_mode(int nn, int ig2 unused)
  1060. {
  1061.     switch (nn) {
  1062.         case 4:
  1063.         insert_mode = 1;
  1064.         break;
  1065.         case 20:
  1066.         auto_newline_mode = 1;
  1067.         break;
  1068.     }
  1069.     return DATA;
  1070. }
  1071.  
  1072. static enum state
  1073. ansi_reset_mode(int nn, int ig2 unused)
  1074. {
  1075.     switch (nn) {
  1076.         case 4:
  1077.         insert_mode = 0;
  1078.         break;
  1079.         case 20:
  1080.         auto_newline_mode = 0;
  1081.         break;
  1082.     }
  1083.     return DATA;
  1084. }
  1085.  
  1086. static enum state
  1087. ansi_status_report(int nn, int ig2 unused)
  1088. {
  1089.     static char cpr[11];
  1090.  
  1091.     switch (nn) {
  1092.         case 5:
  1093.         net_sends("\033[0n");
  1094.         break;
  1095.         case 6:
  1096.         (void) sprintf(cpr, "\033[%d;%dR",
  1097.             (cursor_addr/COLS) + 1, (cursor_addr%COLS) + 1);
  1098.         net_sends(cpr);
  1099.         break;
  1100.     }
  1101.     return DATA;
  1102. }
  1103.  
  1104. static enum state
  1105. ansi_cs_designate(int ig1 unused, int ig2 unused)
  1106. {
  1107.     cs_to_change = strchr(gnnames, ansi_ch) - gnnames;
  1108.     return CSDES;
  1109. }
  1110.  
  1111. static enum state
  1112. ansi_cs_designate2(int ig1 unused, int ig2 unused)
  1113. {
  1114.     csd[cs_to_change] = strchr(csnames, ansi_ch) - csnames;
  1115.     return DATA;
  1116. }
  1117.  
  1118. static enum state
  1119. ansi_select_g0(int ig1 unused, int ig2 unused)
  1120. {
  1121.     cset = CS_G0;
  1122.     return DATA;
  1123. }
  1124.  
  1125. static enum state
  1126. ansi_select_g1(int ig1 unused, int ig2 unused)
  1127. {
  1128.     cset = CS_G1;
  1129.     return DATA;
  1130. }
  1131.  
  1132. static enum state
  1133. ansi_select_g2(int ig1 unused, int ig2 unused)
  1134. {
  1135.     cset = CS_G2;
  1136.     return DATA;
  1137. }
  1138.  
  1139. static enum state
  1140. ansi_select_g3(int ig1 unused, int ig2 unused)
  1141. {
  1142.     cset = CS_G3;
  1143.     return DATA;
  1144. }
  1145.  
  1146. static enum state
  1147. ansi_one_g2(int ig1 unused, int ig2 unused)
  1148. {
  1149.     once_cset = CS_G2;
  1150.     return DATA;
  1151. }
  1152.  
  1153. static enum state
  1154. ansi_one_g3(int ig1 unused, int ig2 unused)
  1155. {
  1156.     once_cset = CS_G3;
  1157.     return DATA;
  1158. }
  1159.  
  1160. static enum state
  1161. ansi_esc3(int ig1 unused, int ig2 unused)
  1162. {
  1163.     return DECP;
  1164. }
  1165.  
  1166. static enum state
  1167. dec_set(int ig1 unused, int ig2 unused)
  1168. {
  1169.     int i;
  1170.  
  1171.     for (i = 0; i <= nx && i < NN; i++)
  1172.         switch (n[i]) {
  1173.             case 1:    /* application cursor keys */
  1174.             appl_cursor = 1;
  1175.             break;
  1176.             case 2:    /* set G0-G3 */
  1177.             csd[0] = csd[1] = csd[2] = csd[3] = CSD_US;
  1178.             break;
  1179.             case 7:    /* wraparound mode */
  1180.             wraparound_mode = 1;
  1181.             break;
  1182.             case 45:    /* reverse-wraparound mode */
  1183.             rev_wraparound_mode = 1;
  1184.             break;
  1185.             case 47:    /* alt buffer */
  1186.             ctlr_altbuffer(True);
  1187.             break;
  1188.         }
  1189.     return DATA;
  1190. }
  1191.  
  1192. static enum state
  1193. dec_reset(int ig1 unused, int ig2 unused)
  1194. {
  1195.     int i;
  1196.  
  1197.     for (i = 0; i <= nx && i < NN; i++)
  1198.         switch (n[i]) {
  1199.             case 1:    /* normal cursor keys */
  1200.             appl_cursor = 0;
  1201.             break;
  1202.             case 7:    /* no wraparound mode */
  1203.             wraparound_mode = 0;
  1204.             break;
  1205.             case 45:    /* no reverse-wraparound mode */
  1206.             rev_wraparound_mode = 0;
  1207.             break;
  1208.             case 47:    /* alt buffer */
  1209.             ctlr_altbuffer(False);
  1210.             break;
  1211.         }
  1212.     return DATA;
  1213. }
  1214.  
  1215. static enum state
  1216. dec_save(int ig1 unused, int ig2 unused)
  1217. {
  1218.     int i;
  1219.  
  1220.     for (i = 0; i <= nx && i < NN; i++)
  1221.         switch (n[i]) {
  1222.             case 1:    /* application cursor keys */
  1223.             saved_appl_cursor = appl_cursor;
  1224.             break;
  1225.             case 7:    /* wraparound mode */
  1226.             saved_wraparound_mode = wraparound_mode;
  1227.             break;
  1228.             case 45:    /* reverse-wraparound mode */
  1229.             saved_rev_wraparound_mode = rev_wraparound_mode;
  1230.             break;
  1231.             case 47:    /* alt buffer */
  1232.             saved_altbuffer = is_altbuffer;
  1233.             break;
  1234.         }
  1235.     return DATA;
  1236. }
  1237.  
  1238. static enum state
  1239. dec_restore(int ig1 unused, int ig2 unused)
  1240. {
  1241.     int i;
  1242.  
  1243.     for (i = 0; i <= nx && i < NN; i++)
  1244.         switch (n[i]) {
  1245.             case 1:    /* application cursor keys */
  1246.             appl_cursor = saved_appl_cursor;
  1247.             break;
  1248.             case 7:    /* wraparound mode */
  1249.             wraparound_mode = saved_wraparound_mode;
  1250.             break;
  1251.             case 45:    /* reverse-wraparound mode */
  1252.             rev_wraparound_mode = saved_rev_wraparound_mode;
  1253.             break;
  1254.             case 47:    /* alt buffer */
  1255.             ctlr_altbuffer(saved_altbuffer);
  1256.             break;
  1257.         }
  1258.     return DATA;
  1259. }
  1260.  
  1261. static enum state
  1262. dec_scrolling_region(int top, int bottom)
  1263. {
  1264.     if (top < 1)
  1265.         top = 1;
  1266.     if (bottom > ROWS)
  1267.         bottom = ROWS;
  1268.     if (top <= bottom && (top > 1 || bottom < ROWS)) {
  1269.         scroll_top = top;
  1270.         scroll_bottom = bottom;
  1271.         cursor_move(0);
  1272.     } else {
  1273.         scroll_top = 1;
  1274.         scroll_bottom = ROWS;
  1275.     }
  1276.     return DATA;
  1277. }
  1278.  
  1279. static enum state
  1280. xterm_text_mode(int ig1 unused, int ig2 unused)
  1281. {
  1282.     nx = 0;
  1283.     n[0] = 0;
  1284.     return TEXT;
  1285. }
  1286.  
  1287. static enum state
  1288. xterm_text_semicolon(int ig1 unused, int ig2 unused)
  1289. {
  1290.     tx = 0;
  1291.     return TEXT2;
  1292. }
  1293.  
  1294. static enum state
  1295. xterm_text(int ig1 unused, int ig2 unused)
  1296. {
  1297.     if (tx < NT)
  1298.         text[tx++] = ansi_ch;
  1299.     return state;
  1300. }
  1301.  
  1302. static enum state
  1303. xterm_text_do(int ig1 unused, int ig2 unused)
  1304. {
  1305. #if defined(X3270_DISPLAY) /*[*/
  1306.     text[tx] = '\0';
  1307.  
  1308.     switch (n[0]) {
  1309.         case 0:    /* icon name and window title */
  1310.         XtVaSetValues(toplevel, XtNiconName, text, NULL);
  1311.         XtVaSetValues(toplevel, XtNtitle, text, NULL);
  1312.         break;
  1313.         case 1:    /* icon name */
  1314.         XtVaSetValues(toplevel, XtNiconName, text, NULL);
  1315.         break;
  1316.         case 2:    /* window_title */
  1317.         XtVaSetValues(toplevel, XtNtitle, text, NULL);
  1318.         break;
  1319.         case 50:    /* font */
  1320.         screen_newfont(text, False);
  1321.         break;
  1322.     }
  1323. #endif /*]*/
  1324.     return DATA;
  1325. }
  1326.  
  1327. static enum state
  1328. ansi_htab_set(int ig1 unused, int ig2 unused)
  1329. {
  1330.     register int col = cursor_addr % COLS;
  1331.  
  1332.     tabs[col/8] |= 1<<(col%8);
  1333.     return DATA;
  1334. }
  1335.  
  1336. static enum state
  1337. ansi_htab_clear(int nn, int ig2 unused)
  1338. {
  1339.     register int col, i;
  1340.  
  1341.     switch (nn) {
  1342.         case 0:
  1343.         col = cursor_addr % COLS;
  1344.         tabs[col/8] &= ~(1<<(col%8));
  1345.         break;
  1346.         case 3:
  1347.         for (i = 0; i < (COLS+7)/8; i++)
  1348.             tabs[i] = 0;
  1349.         break;
  1350.     }
  1351.     return DATA;
  1352. }
  1353.  
  1354. /*
  1355.  * Scroll the screen or the scrolling region.
  1356.  */
  1357. static void
  1358. ansi_scroll(void)
  1359. {
  1360.     held_wrap = False;
  1361.  
  1362.     /* Save the top line */
  1363.     if (scroll_top == 1 && scroll_bottom == ROWS) {
  1364.         if (!is_altbuffer)
  1365.             scroll_save(1, False);
  1366.         ctlr_scroll();
  1367.         return;
  1368.     }
  1369.  
  1370.     /* Scroll all but the last line up */
  1371.     if (scroll_bottom > scroll_top)
  1372.         ctlr_bcopy(scroll_top * COLS,
  1373.             (scroll_top - 1) * COLS,
  1374.             (scroll_bottom - scroll_top) * COLS,
  1375.             1);
  1376.  
  1377.     /* Clear the last line */
  1378.     ctlr_aclear((scroll_bottom - 1) * COLS, COLS, 1);
  1379. }
  1380.  
  1381. /* Callback for when we enter ANSI mode. */
  1382. static void
  1383. ansi_in3270(Boolean in3270)
  1384. {
  1385.     if (!in3270)
  1386.         (void) ansi_reset(0, 0);
  1387. }
  1388.  
  1389.  
  1390. /*
  1391.  * External entry points
  1392.  */
  1393.  
  1394. void
  1395. ansi_init(void)
  1396. {
  1397.     register_schange(ST_3270_MODE, ansi_in3270);
  1398. }
  1399.  
  1400. void
  1401. ansi_process(unsigned int c)
  1402. {
  1403.     c &= 0xff;
  1404.     ansi_ch = c;
  1405.  
  1406.     scroll_to_bottom();
  1407.  
  1408. #if defined(X3270_TRACE) /*[*/
  1409.     if (toggled(SCREEN_TRACE))
  1410.         trace_char((char)c);
  1411. #endif /*]*/
  1412.  
  1413.     state = (*ansi_fn[st[(int)state][c]])(n[0], n[1]);
  1414. }
  1415.  
  1416. void
  1417. ansi_send_up(void)
  1418. {
  1419.     if (appl_cursor)
  1420.         net_sends("\033OA");
  1421.     else
  1422.         net_sends("\033[A");
  1423. }
  1424.  
  1425. void
  1426. ansi_send_down(void)
  1427. {
  1428.     if (appl_cursor)
  1429.         net_sends("\033OB");
  1430.     else
  1431.         net_sends("\033[B");
  1432. }
  1433.  
  1434. void
  1435. ansi_send_right(void)
  1436. {
  1437.     if (appl_cursor)
  1438.         net_sends("\033OC");
  1439.     else
  1440.         net_sends("\033[C");
  1441. }
  1442.  
  1443. void
  1444. ansi_send_left(void)
  1445. {
  1446.     if (appl_cursor)
  1447.         net_sends("\033OD");
  1448.     else
  1449.         net_sends("\033[D");
  1450. }
  1451.  
  1452. void
  1453. ansi_send_home(void)
  1454. {
  1455.     net_sends("\033[H");
  1456. }
  1457.  
  1458. void
  1459. ansi_send_clear(void)
  1460. {
  1461.     net_sends("\033[2K");
  1462. }
  1463.  
  1464. void
  1465. ansi_send_pf(int nn)
  1466. {
  1467.     static char fn_buf[6];
  1468.     static int code[] = {
  1469.         /*
  1470.          * F1 through F12 are VT220 codes. (Note the discontinuity --
  1471.          * \E[16~ is missing)
  1472.          */
  1473.         11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24,
  1474.         /*
  1475.          * F13 through F20 are defined for xterm.
  1476.          */
  1477.         25, 26, 28, 29, 31, 32, 33, 34,
  1478.         /*
  1479.          * F21 through F24 are x3270 extensions.
  1480.          */
  1481.         35, 36, 37, 38
  1482.     };
  1483.  
  1484.     if (nn < 1 || nn > sizeof(code)/sizeof(code[0]))
  1485.         return;
  1486.     (void) sprintf(fn_buf, "\033[%d~", code[nn-1]);
  1487.     net_sends(fn_buf);
  1488. }
  1489.  
  1490. void
  1491. ansi_send_pa(int nn)
  1492. {
  1493.     static char fn_buf[4];
  1494.     static char code[4] = { 'P', 'Q', 'R', 'S' };
  1495.  
  1496.     if (nn < 1 || nn > 4)
  1497.         return;
  1498.     (void) sprintf(fn_buf, "\033O%c", code[nn-1]);
  1499.     net_sends(fn_buf);
  1500. }
  1501.  
  1502. void
  1503. toggle_lineWrap(struct toggle *t unused, enum toggle_type type unused)
  1504. {
  1505.     if (toggled(LINE_WRAP))
  1506.         wraparound_mode = 1;
  1507.     else
  1508.         wraparound_mode = 0;
  1509. }
  1510.  
  1511. #endif /*]*/
  1512.